/**************************************************************************************************************************************************************************************************
*         *       *  *  *                         *                 *      **********                         *******************     
**        *    *           *                       *               *      *                       ** ** *             *
* *       *   *             *                       *             *       *                    * *                    *
*  *      *  *               *                       *           *        *                 * *                       *
*   *     *  *               *                        *         *         *               **                          *
*    *	  *  *               *                         *       *           **********    *                            *
*     *   *   *             *                           *     *           *               **                          *
*      *  *    *           *                             *   *            *                 * *                       *
*       * *      *        *                               * *             *                    * *                    *
*         *        * *  *                                  *               ***********            ** ** *             *
******************************************************************************************************************************************************************************************************/
#include <iostream>
using namespace std;
template<typename chartype>
class Sting_node{
public:
	chartype elemc;
	Sting_node<chartype> * next;
};
/*
template<typename chartype>
class Sting_part{
public:
	Sting_part(Sting_node<chartype> ** firstptr)
	{
		Sting_part::firstptr=firstptr
	}

void operator=(chartype * chars)
{


}
void operator=(chartype chara){



}
		
private:
	void inline clear(){
	firstptr=NULL;
	}
Sting_node<chartype> ** firstptr;
};*/
template<typename chartype,chartype nullchar=(chartype)(0)>
class Sting_List_Generic{
	friend std::istream & operator>><chartype,nullchar>(istream &input,Sting_List_Generic<chartype,nullchar> & target );
	friend std::ostream & operator<<<chartype,nullchar>(ostream &output,Sting_List_Generic<chartype,nullchar> &target );
public:
Sting_List_Generic(){
		 top=NULL;
		 prev=NULL;
		 last=NULL;
		 size=0;
	}
/*
Sting_List_Generic(chartype *str){
	Sting_node<chartype,nullchar>** cur=&top;	
	}

Sting_List_Generic(std::string str){




}*/
/*
The copy constructor , it facilitate making more than version of the Sting class without sharing pointers
between the Sting object bodies , it make use of the private function copy

*/
	Sting_List_Generic(Sting_List_Generic & source){
	Sting_List_Generic();
	copy(source);
	}
	/*
	The function that returns the size of the current sting;
	*/
	int getsize(){return size;}
	/*
	The function that allows inserting a character in a random position in the string , if the position is larger than the current size ,
	it will append the character
	
	*/
	void insert(int pos,chartype c){
		Sting_node<chartype>** cur=&top;
		while(*cur!=nullchar&&pos--!=0)
			cur=&((*cur)->next);
		Sting_node<chartype> * cp=new Sting_node<chartype>;
		cp->elemc=c;
		cp->next=*cur;
		*cur=cp;
		last=*cur;
		size++;
	}
	/*the square bracket operator that allow accessing a random character in the Sting object it allow modification 
	(since it return it's reference)*/
	chartype & operator[](int pos)const{
		Sting_node<chartype>* cur=top;
	for(int i=0;i<pos&&cur!=NULL;i++,cur=cur->next);
	return cur->elemc;
	
	}
	/*The function that allows inserting a character in a random position in the string */
	void remove(int pos){
	Sting_node<chartype>** cur=&top;
	while(*cur!=NULL&&pos--!=0)
			cur=&((*cur)->next);
	Sting_node<chartype> * cp= (*cur)->next;
	delete *cur;
	*cur =cp;
	size--;
	}
	/*the assignment operator , it allows an object of type Sting to be assigned to another object of the same type without risking 
	the shared referencing by pointers */
	Sting_List_Generic<chartype,nullchar> & operator=(Sting_List_Generic<chartype,nullchar>& dest){
		clear();
		copy(dest);
		return (*this);
	}
	/*The function that clear the Sting object and return it to its empty state*/
	void clear(){
		for(Sting_node<chartype>* cur=top;cur!=NULL;){
			Sting_node<chartype>* next=cur->next;
			delete cur;
			cur=next;
		}
		 top=NULL;
		 prev=NULL;
		 last=NULL;
		 size=0;
	}
	/*The equality operator to compare two string objects and identify whether they are equal or not*/
	bool operator ==(Sting_List_Generic<chartype,nullchar>& right){
		if(size!=right.size)
			return false;
		Sting_node<chartype> * cur=top;
		Sting_node<chartype> * cur2=right.top;
	for(;cur!=NULL;cur=cur->next,cur2=cur2->next)
		if(cur2->elemc!=cur->elemc)
			return false;
		return true;
		
	}
private:
	/*a simple function to copy a sting object to another*/
void inline copy (Sting_List_Generic<chartype,nullchar> &source){
	Sting_node<chartype>** curp=&top;
	for(Sting_node<chartype>* cur=source.top;cur!=NULL;cur=cur->next)
	{	
		Sting_node<chartype> * cp=new Sting_node<chartype>;
		cp->elemc=cur->elemc;
		*curp=cp;
		curp=&cp->next;
		
	}
	*curp=NULL;
	size=source.size;
	}
	Sting_node< chartype> * top;
	Sting_node< chartype> * prev;
	Sting_node< chartype> * last;
	int size;
};
/*The overloading of the binary left shift operator with class ostream (basic_ostream<char>) to allow objects of the mentioned 
class to deal with the Sting object*/
template<typename chartype,chartype nullchar>
std::ostream & operator<<(ostream &output,Sting_List_Generic<chartype,nullchar> &target ){
	
	for(Sting_node<chartype>* cur=target.top;cur!=NULL;cur=cur->next)
		cout<<cur->elemc;
return output;
}
/*The overloading of the binary right shift operator with class istream (basic_istream<char>) to allow objects of the mentioned 
class to deal with the Sting object*/
template<typename chartype,chartype nullchar>
std::istream & operator>>(istream &input,Sting_List_Generic<chartype,nullchar> & target ){
target.clear();
chartype k;
input.get(k);
int pos=0;
while(k!='\n')
{
	target.insert(pos++,k);
	input.get(k);
}
return input;
}
/* A type defenetion to facilitate usage of the common Sting (a Sting of charachters) */
typedef Sting_List_Generic<char> Sting;